#ifndef EM80_PAYLOAD_FACTORY_H
#define EM80_PAYLOAD_FACTORY_H

#include "../packets.hpp"
#include "../v8stdint.h"

#include <vector>
#include <map>
#include <string>

#include <functional>
#include <memory>

#include <boost/noncopyable.hpp>




namespace em80_driver
{

/**
 * Class for creating EM80 payloads from raw data
 */
class EM80PayloadFactory : private boost::noncopyable
{
public:
    /** Return the global factory object */
    static EM80PayloadFactory* getFactory();

    static EM80PayloadBasePtr createPayload(const EM80PacketPtr &packet, std::string *what);

    typedef std::function<EM80PayloadBasePtr(const EM80PacketPtr&)> CreateFn;

    /** Register a packet type with the factory */
    static void registerPayloadType(int payload_id, CreateFn fn);

private:

    typedef std::map<int, CreateFn> FactoryMap;
    static FactoryMap* getMap();        //it is used internally! : not need to be monitored by std::shared_ptr<T>
};

/** Use this macro to register payloads */
#define REGISTER_PAYLOAD_TYPE(id, klass)   \
class klass##Factory \
{\
public: \
    klass##Factory() \
    { \
      EM80PayloadFactory::registerPayloadType((id), &klass##Factory::create); \
    }\
    static EM80PayloadBasePtr create(const EM80PacketPtr &packet) \
    {\
        return EM80PayloadBasePtr(new klass(packet));\
    }\
};\
static klass##Factory gloabl_##klass##Factory;

}
#endif /* EM80_PAYLOAD_FACTORY_H */
